package flow

import "fmt"

// Factory is a factory for creating components.
type Factory struct {
	registry map[string]registryEntry
}

// registryEntry is a registry entry for a component.
type registryEntry struct {
	constructor Constructor
	info        ComponentInfo
}

// Constructor is a constructor for a component.
type Constructor func() (interface{}, error)

func NewFactory() *Factory {
	return &Factory{
		registry: make(map[string]registryEntry),
	}
}

// Register registers a component with the factory.
func (f *Factory) Register(componentName string, constructor Constructor) error {
	_, exists := f.registry[componentName]
	if exists {

		return fmt.Errorf("component %s already registered", componentName)
	}
	f.registry[componentName] = registryEntry{
		constructor: constructor,
		info: ComponentInfo{
			Name: componentName,
		},
	}
	return nil
}

// Unregister unregisters a component from the factory.
func (f *Factory) Unregister(componentName string) error {
	_, exists := f.registry[componentName]
	if !exists {
		return fmt.Errorf("component %s not registered", componentName)
	}
	delete(f.registry, componentName)
	return nil
}

// Create creates a component from the factory.
func (f *Factory) Create(componentName string) (interface{}, error) {
	info, exists := f.registry[componentName]
	if !exists {
		return nil, fmt.Errorf("component %s not registered", componentName)
	}
	return info.constructor()
}
